using System;
using System.Collections.Generic;
using System.Text;
using SdlDotNet.Graphics;
using SdlDotNet.Core;
using SnakeCharp.Entity;
using SnakeCharp.UI;
using SnakeCharp.Interfaces;

namespace SnakeCharp.Game
{
    /// <summary>
    /// This handle all the game logic
    /// and is responsible for running and updating the current game.
    /// </summary>
    public class GameHandler
    {
        private Snake player;
        private List<BaseEntity> entityList;
        private Random randomGenerator;
        private GameHud hud;


        //Level specific fields
        private int updatesBetweenTailNodeRemoved = 50;
        private int updatesBetweenTailNodeRemovedCounter = 0;

        public GameHandler(Snake player)
        {
            this.player = player;
            this.randomGenerator = new Random();
            this.hud = new GameHud();

            //Setup EntityList
            entityList = new List<BaseEntity>();
            
            //Spawn default testing mise
            SpawnMouse();
            SpawnMouse();
            SpawnMouse();
        }


        /// <summary>
        /// Renders all the Entity in the game on the destinationSurface.
        /// </summary>
        /// <param name="destinationSurface">The destination surface. This will typically be the Video.Screen.</param>
        public void Render(Surface destinationSurface, float interpolation)
        {
            //Render all game entities
            foreach (BaseEntity entity in entityList)
            {
                entity.Render(interpolation, destinationSurface);
            }
           
            //Render player
            this.player.Render(interpolation, destinationSurface);

            //Render Hud
            this.hud.Render(destinationSurface);
        }

        /// <summary>
        /// Updates all the Entities in the game. And the current game.
        /// </summary>
        /// <param name="inputController">The input controller.</param>
        /// <param name="e">The <see cref="SdlDotNet.Core.TickEventArgs"/> instance containing the event data.</param>
        public void Update(Controller inputController, TickEventArgs e)
        {
            //Update Player
            this.player.Update(inputController, e);

            //Remove TailNode from player
            if (updatesBetweenTailNodeRemovedCounter >= updatesBetweenTailNodeRemoved)
            {
                this.player.Tail.RemoveTailNode();
                updatesBetweenTailNodeRemovedCounter = 0;
            }
            else
                updatesBetweenTailNodeRemovedCounter++;

            
            //Update entities
            foreach (BaseEntity entity in entityList)
            {
                entity.Update();
            }

            //Collision Check
            for (int i = 0; i < entityList.Count; i++)
            {
                if (this.player.IntersectsWithRadius(entityList[i], entityList[i].Height / 2))
                {
                    if (entityList[i] is IEatable)
                    {
                        ((IEatable)entityList[i]).ActOponCollision(this.player);

                        //Check if this IEatable "IsGone" is true
                        if (((IEatable)entityList[i]).IsEaten)
                        {
                            //TEST: Count points
                            hud.Score += ((IEatable)entityList[i]).Points;
                            this.player.Tail.AddTailNode();

                            entityList.Remove(entityList[i]);
                        }
                    }

                    //TEST: Add mouse
                    SpawnMouse();
                }
            }

            //Update Hud
            this.hud.Update();
        }

       

        /// <summary>
        /// Spawns the mouse. ONLY FOR TESTING
        /// </summary>
        private void SpawnMouse()
        {
            if(entityList.Count <= 10)
                entityList.Add(new Mouse(randomGenerator.Next(20, Configurations.ScreenWidth - 20), randomGenerator.Next(20, Configurations.ScreenHeight - 20)));
        }
    }
}
